//
// Created by Mengyu Li on 2021/3/9.
//

import Foundation
import LMDB

public class Store {
    public let name: String

    private let database: Database

    public lazy var async = AsyncStore(store: self)
    public lazy var sync = SyncStore(store: self)

    public init(name: String, environment: Environment) throws {
        precondition(!name.isEmpty, "name is empty")
        self.name = name
        database = try environment.openDatabase(name: name)
    }
}

extension Store {
    func put<V: DataConvertible, K: DataConvertible>(value: V, forKey key: K) throws {
        try database.put(value: value, forKey: key)
    }

    func get<V: DataConvertible, K: DataConvertible>(key: K) throws -> V? {
        let value: V? = try database.get(key: key)
        return value
    }

    func delete<K: DataConvertible>(key: K) throws {
        try database.deleteValue(forKey: key)
    }
}

extension Store {
    func empty() throws {
        try database.empty()
    }

    @available(*, unavailable)
    func drop() throws {
        try database.drop()
    }
}

extension Store: Hashable {
    public func hash(into hasher: inout Hasher) { hasher.combine(name) }
}

extension Store: Equatable {
    public static func == (lhs: Store, rhs: Store) -> Bool { lhs.name == rhs.name }
}
